#ifndef __BOOTPARAM_H__
#define __BOOTPARAM_H__

#include <cnix/screen_info.h>
#include <cnix/apm_bios.h>
#include <cnix/ist.h>
#include <cnix/edid.h>
#include <cnix/edd.h>
#include <cnix/e820.h>
#include <cnix/types.h>

/* setup data types */
#define SETUP_NONE      0
#define SETUP_E820_EXT      1

/* extensible setup data list node */
struct setup_data {
  u64_t next;
  u32_t type;
  u32_t len;
  u8_t data[0];
};

struct setup_header {
  u8_t  setup_sects;
  u16_t root_flags;
  u32_t syssize;
  u16_t ram_size;
#define RAMDISK_IMAGE_START_MASK  0x07FF
#define RAMDISK_PROMPT_FLAG   0x8000
#define RAMDISK_LOAD_FLAG   0x4000
  u16_t vid_mode;
  u16_t root_dev;
  u16_t boot_flag;
  u16_t jump;
  u32_t header;
  u16_t version;
  u32_t realmode_swtch;
  u16_t start_sys;
  u16_t kernel_version;
  u8_t  type_of_loader;
  u8_t  loadflags;
#define LOADED_HIGH (1<<0)
#define QUIET_FLAG  (1<<5)
#define KEEP_SEGMENTS (1<<6)
#define CAN_USE_HEAP  (1<<7)
  u16_t setup_move_size;
  u32_t code32_start;
  u32_t ramdisk_image;
  u32_t ramdisk_size;
  u32_t bootsect_kludge;
  u16_t heap_end_ptr;
  u8_t  ext_loader_ver;
  u8_t  ext_loader_type;
  u32_t cmd_line_ptr;
  u32_t initrd_addr_max;
  u32_t kernel_alignment;
  u8_t  relocatable_kernel;
  u8_t  _pad2[3];
  u32_t cmdline_size;
  u32_t hardware_subarch;
  u64_t hardware_subarch_data;
  u32_t payload_offset;
  u32_t payload_length;
  u64_t setup_data;
} __attribute__((packed));

struct sys_desc_table {
  u16_t length;
  u8_t  table[14];
};

struct efi_info {
  u32_t efi_loader_signature;
  u32_t efi_systab;
  u32_t efi_memdesc_size;
  u32_t efi_memdesc_version;
  u32_t efi_memmap;
  u32_t efi_memmap_size;
  u32_t efi_systab_hi;
  u32_t efi_memmap_hi;
};

/* The so-called "zeropage" */
struct boot_params {
  struct screen_info screen_info;     /* 0x000 */
  struct apm_bios_info apm_bios_info;   /* 0x040 */
  u8_t  _pad2[4];         /* 0x054 */
  u64_t  tboot_addr;        /* 0x058 */
  struct ist_info ist_info;     /* 0x060 */
  u8_t  _pad3[16];        /* 0x070 */
  u8_t  hd0_info[16]; /* obsolete! */   /* 0x080 */
  u8_t  hd1_info[16]; /* obsolete! */   /* 0x090 */
  struct sys_desc_table sys_desc_table;   /* 0x0a0 */
  u8_t  _pad4[144];       /* 0x0b0 */
  struct edid_info edid_info;     /* 0x140 */
  struct efi_info efi_info;     /* 0x1c0 */
  u32_t alt_mem_k;        /* 0x1e0 */
  u32_t scratch;    /* Scratch field! */  /* 0x1e4 */
  u8_t  e820_entries;       /* 0x1e8 */
  u8_t  eddbuf_entries;       /* 0x1e9 */
  u8_t  edd_mbr_sig_buf_entries;      /* 0x1ea */
  u8_t  _pad6[6];         /* 0x1eb */ 
  struct setup_header hdr;    /* setup header */  /* 0x1f1 */
  u8_t  _pad7[0x290-0x1f1-sizeof(struct setup_header)];
  u32_t edd_mbr_sig_buffer[EDD_MBR_SIG_MAX];  /* 0x290 */
  struct e820entry e820_map[E820MAX];   /* 0x2d0 */
  u8_t  _pad8[48];        /* 0xcd0 */
  struct edd_info eddbuf[EDDMAXNR];   /* 0xd00 */
  u8_t  _pad9[276];       /* 0xeec */
} __attribute__((packed));

#endif
